﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using KinConquer.Entities;
using KinConquer.Sockets;
using KinSocket;

namespace KinConquer
{
    public class Program
    {
        public unsafe static void Main(string[] args)
        {
            Console.Title = "Game - KinConquer";

            Program.Database = new KinConquer.Database();

            GameSocket auth = new GameSocket();

            Console.WriteLine("Online");
            while (true)
            {
                Console.ReadLine();
                /*foreach (KinSocket.Connection con in GameConnections.EnumerableValues)
                {
                    if (con.ReceiveQueue.Count > 0)
                    {
                        Byte[] Data = con.ReceiveQueue.Dequeue();
                        fixed (byte* pData = Data)
                        {
                            Packets.Delegates.PacketHandles[BitConverter.ToUInt16(Data, 2)](pData, con);
                        }
                    }
                }*/
                //Thread.Sleep(10);
            }
        }

        public static Entities.Hero GetHero(UInt32 identifier)
        {
            Entities.Hero h = null;
            Program.HeroPool.TryGetValue(identifier, out h);
            return h;
        }

        public static Database Database;

        public static Counter GameConID = new Counter(1, 99999);

        public unsafe static void OnTimer(Connection con)
        {
            con.DoQueueSend();
            if (con.ReceiveQueue.Count > 0)
            {
                Byte[] Data = con.ReceiveQueue.Dequeue();
                fixed (byte* pData = Data)
                {
                    Packets.Delegates.PacketHandles[BitConverter.ToUInt16(Data, 2)](pData, con);
                }
            }

            Entities.Hero h = GetHero(con.Identifier);
            if (h != null)
            {
                if (h.ActionQueue.Count > 0)
                {
                    QdAction action = h.ActionQueue.Dequeue();
                    switch (action.Type)
                    {
                        case QdActionType.SendRangePacket:
                            {
                                Int32 distance = (action.Int == 0) ? Constants.ViewDistance : action.Int;
                                var heros = from hc in HeroPool.EnumerableValues where h.ObjectType.HasFlag(ObjectType.Hero) select hc;
                                foreach (IMapObject o in heros)
                                {
                                    if (Entities.Calculations.Misc.Distance(h.X, h.Y, o.X, o.Y) < distance)
                                    {
                                        Hero tmp = (o as Hero);
                                        tmp.Owner.Send(action.Data);
                                        if (action.Bool)
                                        {
                                            if (!tmp.Screen.Contains(h.Identifier))
                                            {
                                                tmp.Screen.Add(h);
                                                tmp.Owner.Send(h.SpawnPacket);
                                            }
                                        }
                                    }
                                }
                                break;
                            }
                        case QdActionType.SendScreenPacket:
                            {
                                h.Screen.Send(action.Data);
                                break;
                            }
                        case QdActionType.CleanUpScreen:
                            {
                                h.Screen.Cleanup();
                                break;
                            }
                        case QdActionType.UpdateScreen:
                            {
                                h.Screen.GetScreen(action.Bool, false);
                                break;
                            }
                        case QdActionType.UpdateCleanScreen:
                            {
                                h.Screen.Cleanup();
                                h.Screen.GetScreen(action.Bool, false);
                                break;
                            }
                        case QdActionType.GetSurroundings:
                            {
                                h.Screen.GetScreen(true, true);
                                break;
                            }
                    }
                }
            }
        }

        public static DictionaryV2<UInt32, KinSocket.Connection> GameConnections
            = new DictionaryV2<UInt32, KinSocket.Connection>();
        public static DictionaryV2<UInt32, Entities.Hero> HeroPool
            = new DictionaryV2<UInt32, Entities.Hero>();
    }
}
